#pragma once
#include "Log.hpp"
#include "mutex.hpp"
#include "Cond.hpp"
#include "Thread.hpp"
#include "Task.hpp"

#include <vector>
#include <queue>

using namespace LogModule;
using namespace MyThreadModule;
using namespace CondModule;
using namespace mutex_module;

namespace ThreadPoolModule
{
    static const int gnum = 5;
    template <typename T>
    class ThreadPool
    {
    private:
        void WakeUpOne()
        {
            _cond.Signal();
        }
        void WakeUpAll()
        {
            _cond.Broadcast();
        }
        void Wait()
        {
            _cond.Wait(_mutex);
        }
        ThreadPool(int num = gnum) // 私有的构造函数
            : _isRun(false), _num(num)
        {
            // 创建线程
            for (int i = 0; i < _num; i++)
            {
                _threads.emplace_back([this]()
                                      { Handler(); });
            }
        }

    public:
        // 禁用拷贝构造
        ThreadPool(const ThreadPool &obj) = delete;
        // 禁用赋值构造
        ThreadPool &operator=(const ThreadPool &obj) = delete;
        // 对外提供的实例接口
        static ThreadPool<T> *GetInstance()
        {
            if (thread_pool == nullptr)
            {
                LockGuard lockguard(_static_mutex);
                LOG(LogLevel::INFO) << "线程实例获取成功!!!";
                if (thread_pool == nullptr)
                {
                    thread_pool = new ThreadPool();
                    LOG(LogLevel::INFO) << "线程实例创建成功!!!";
                    thread_pool->Start();
                }
            }
            return thread_pool;
        }
        void Handler()
        {
            while (true)
            {
                T task;
                {
                    LockGuard lockguard(_mutex);
                    while (_task.empty() && _isRun) // 队列为空,且线程池没有停止才需要进行等待
                    {
                        _sleepNum++;
                        Wait();
                        _sleepNum--;
                    }

                    if (_task.empty() && !_isRun)
                    {
                        LOG(LogLevel::INFO) << "任务处理完毕 , 线程退出...";
                        break;
                    }
                    task = _task.front();
                    _task.pop();
                }
                task(); // 线程获取到任务时就可以丢掉锁了
            }
        }
        bool Enqueue(const T &task)
        {
            if (_isRun)
            {
                LockGuard lockguard(_mutex);
                // 插入任务
                _task.push(task);
                // 尝试唤醒
                if (_sleepNum > 0) // 如果还有睡眠的线程,则唤醒
                {
                    WakeUpOne();
                }
                return true;
            }
            return false;
        }
        void Start()
        {
            if (!_isRun)
            {
                for (int i = 0; i < _num; i++)
                {
                    _threads[i].Start();
                }
                _isRun = true;
            }
        }
        void Stop()
        {
            if (_isRun)
            {
                // for (int i = 0; i < _num; i++)
                // {
                //     _threads[i].Stop();
                // }
                LockGuard lockguard(_mutex);
                _isRun = false;
                WakeUpAll();
            }
        }
        void Join()
        {
            for (int i = 0; i < _num; i++)
            {
                _threads[i].Join();
            }
        }

    private:
        std::vector<Thread> _threads;
        std::queue<T> _task;
        int _num;

        int _sleepNum;

        bool _isRun;
        Mutex _mutex;
        Cond _cond;

        // 静态对象
        static ThreadPool *thread_pool;
        static Mutex _static_mutex;
    };
    // 类外初始化静态变量
    template <typename T>
    ThreadPool<T> *ThreadPool<T>::thread_pool = nullptr;
    //和静态变量配套一个静态锁
    template <typename T>
    Mutex ThreadPool<T>::_static_mutex;

    // static const int gnum = 5;
    // template <typename T>
    // class ThreadPool
    // {
    // private:
    //     void WakeUpOne()
    //     {
    //         _cond.Signal();
    //     }
    //     void Wait()
    //     {
    //         _cond.Wait(_mutex);
    //     }

    // public:
    //     ThreadPool(int num = gnum)
    //         : _isRun(false), _num(num)
    //     {
    //         // 创建线程
    //         for (int i = 0; i < _num; i++)
    //         {
    //             _threads.emplace_back([this]()
    //                                   { Handler(); });
    //         }
    //     }
    //     void Handler()
    //     {
    //         while (true)
    //         {
    //             T task;
    //             {
    //                 LockGuard lockguard(_mutex);
    //                 while (_task.empty() && _isRun) // 队列为空,且线程池没有停止才需要进行等待
    //                 {
    //                     _sleepNum++;
    //                     Wait();
    //                     _sleepNum--;
    //                 }

    //                 if(_task.empty() && !_isRun)
    //                 {
    //                     LOG(LogLevel::INFO) << "任务处理完毕 , 线程退出...";
    //                     break;
    //                 }
    //                 task = _task.front();
    //                 _task.pop();
    //             }
    //             task(); // 线程获取到任务时就可以丢掉锁了
    //         }
    //     }
    //     bool Enqueue(const T &task)
    //     {
    //         if (_isRun)
    //         {
    //             LockGuard lockguard(_mutex);
    //             // 插入任务
    //             _task.push(task);
    //             // 尝试唤醒
    //             if (_sleepNum > 0) // 如果还有睡眠的线程,则唤醒
    //             {
    //                 WakeUpOne();
    //             }
    //             return true;
    //         }
    //         return false;
    //     }
    //     void Start()
    //     {
    //         if (!_isRun)
    //         {
    //             for (int i = 0; i < _num; i++)
    //             {
    //                 _threads[i].Start();
    //             }
    //             _isRun = true;
    //         }
    //     }
    //     void Stop()
    //     {
    //         if (_isRun)
    //         {
    //             for (int i = 0; i < _num; i++)
    //             {
    //                 _threads[i].Stop();
    //             }
    //             _isRun = false;
    //         }
    //     }
    //     void Join()
    //     {
    //         for (int i = 0; i < _num; i++)
    //         {
    //             _threads[i].Join();
    //         }
    //     }

    // private:
    //     std::vector<Thread> _threads;
    //     std::queue<T> _task;
    //     int _num;

    //     int _sleepNum;

    //     bool _isRun;
    //     Mutex _mutex;
    //     Cond _cond;
    // };

}